/**
 * 错误处理辅助工具
 * 提供统一的错误处理机制
 */

// 错误类型常量
export const ERROR_TYPES = {
  API: 'api_error',        // API调用错误
  VALIDATION: 'validation_error', // 表单验证错误
  NETWORK: 'network_error',   // 网络错误
  PERMISSION: 'permission_error', // 权限错误
  AUTH: 'auth_error',       // 认证错误
  SYSTEM: 'system_error',    // 系统错误
  UNKNOWN: 'unknown_error'   // 未知错误
};

// 错误严重程度
export const ERROR_SEVERITY = {
  INFO: 'info',        // 信息级
  WARNING: 'warning',  // 警告级
  ERROR: 'error',      // 错误级
  CRITICAL: 'critical' // 严重错误
};

/**
 * 错误处理工具类
 * 提供统一的错误处理方法，与MobX Store集成
 */
export const errorHandler = {
  /**
   * 处理页面错误
   * @param {Error|String} error 错误对象或错误消息
   * @param {String} moduleName 模块名称，用于错误分类
   * @param {Object} options 附加选项
   * @returns {Boolean} 处理结果
   */
  handlePageError(error, moduleName = null, options = {}) {
    // 默认选项
    const defaultOpts = {
      showToast: true,       // 是否显示Toast提示
      logError: true,        // 是否记录日志
      duration: 2000,        // Toast显示时长
      throwError: false,     // 是否继续抛出错误
      errorType: ERROR_TYPES.UNKNOWN // 错误类型
    };
    
    // 合并选项
    const opts = { ...defaultOpts, ...options };
    
    // 提取错误消息
    const errorMsg = error instanceof Error ? error.message : String(error);
    
    // 记录日志
    if (opts.logError) {
      console.error(`[${moduleName || 'App'}]`, error);
    }
    
    // 全局错误处理（如果在Store内，会自动设置错误状态）
    if (this.store && typeof this.store.setError === 'function') {
      this.store.setError(errorMsg);
    }
    
    // 显示错误提示
    if (opts.showToast) {
      this.showToast('error', errorMsg, opts.duration);
    }
    
    // 是否继续抛出错误
    if (opts.throwError) {
      throw error;
    }
    
    return false;
  },
  
  /**
   * 处理API调用错误
   * @param {Error|String} error 错误对象或错误消息
   * @param {Boolean} silent 是否静默处理（不显示Toast）
   * @param {Object} options 附加选项
   * @returns {Boolean} 处理结果
   */
  handleApiError(error, silent = false, options = {}) {
    // 默认选项
    const defaultOpts = {
      logError: true,        // 是否记录日志
      duration: 2000,        // Toast显示时长
      moduleName: 'api',     // 模块名称
      throwError: false,     // 是否继续抛出错误
      loadingKey: null,      // 需要重置的加载状态键
      errorType: ERROR_TYPES.API // 错误类型
    };
    
    // 合并选项
    const opts = { ...defaultOpts, ...options };
    
    // 提取错误消息
    const errorMsg = error instanceof Error ? error.message : String(error);
    
    // 记录日志
    if (opts.logError) {
      console.error(`[API Error][${opts.moduleName}]`, error);
    }
    
    // 重置加载状态
    if (opts.loadingKey && this.store && typeof this.store.setLoading === 'function') {
      this.store.setLoading(opts.loadingKey, false);
    }
    
    // 设置错误状态
    if (this.store && typeof this.store.setError === 'function') {
      this.store.setError(errorMsg);
    }
    
    // 显示错误提示
    if (!silent) {
      this.showToast('error', errorMsg || '网络请求失败', opts.duration);
    }
    
    // 是否继续抛出错误
    if (opts.throwError) {
      throw error;
    }
    
    return false;
  },
  
  /**
   * 处理表单错误
   * @param {Error|String|Object} error 错误对象、错误消息或表单错误对象 {field, message}
   * @param {Object} form 表单对象（可选），用于设置字段错误
   * @param {Object} options 附加选项
   * @returns {Boolean} 处理结果
   */
  handleFormError(error, form = null, options = {}) {
    // 默认选项
    const defaultOpts = {
      showToast: true,       // 是否显示Toast提示
      logError: true,        // 是否记录日志
      duration: 2000,        // Toast显示时长
      moduleName: 'form',    // 模块名称
      throwError: false,     // 是否继续抛出错误
      errorType: ERROR_TYPES.VALIDATION // 错误类型
    };
    
    // 合并选项
    const opts = { ...defaultOpts, ...options };
    
    // 提取错误消息和字段
    let errorMsg, fieldName;
    
    if (error instanceof Error) {
      errorMsg = error.message;
    } else if (typeof error === 'string') {
      errorMsg = error;
    } else if (error && typeof error === 'object') {
      errorMsg = error.message || '表单验证失败';
      fieldName = error.field;
    } else {
      errorMsg = '未知表单错误';
    }
    
    // 记录日志
    if (opts.logError) {
      console.error(`[Form Error][${opts.moduleName}]`, error);
    }
    
    // 设置错误状态
    if (this.store && typeof this.store.setError === 'function') {
      this.store.setError(errorMsg);
    }
    
    // 如果有表单对象且有字段名，则设置字段错误
    if (form && fieldName && typeof form.setError === 'function') {
      form.setError(fieldName, errorMsg);
    } else if (opts.showToast) {
      // 否则显示一般错误提示
      this.showToast('error', errorMsg, opts.duration);
    }
    
    // 是否继续抛出错误
    if (opts.throwError) {
      throw error;
    }
    
    return false;
  },
  
  /**
   * 绑定到Store
   * @param {Object} store MobX Store实例
   * @returns {Object} 错误处理工具实例
   */
  bindStore(store) {
    this.store = store;
    return this;
  },
  
  /**
   * 清除错误
   */
  clearError() {
    if (this.store && typeof this.store.setError === 'function') {
      this.store.setError(null);
    }
  },
  
  /**
   * 显示Toast提示
   * @param {String} type 提示类型：success, error, info, warning
   * @param {String} message 提示消息
   * @param {Number} duration 显示时长
   */
  showToast(type, message, duration = 2000) {
    // 使用微信小程序API显示提示
    const toastConfig = {
      title: message,
      duration: duration
    };
    
    switch (type) {
      case 'success':
        wx.showToast({
          ...toastConfig,
          icon: 'success'
        });
        break;
      case 'error':
        wx.showToast({
          ...toastConfig,
          icon: 'none'
        });
        break;
      case 'info':
      case 'warning':
      default:
        wx.showToast({
          ...toastConfig,
          icon: 'none'
        });
        break;
    }
  },
  
  /**
   * 显示成功提示
   * @param {String} message 成功消息
   * @param {Number} duration 显示时长
   */
  showSuccess(message, duration = 2000) {
    this.showToast('success', message, duration);
  },
  
  /**
   * 显示错误提示
   * @param {String} message 错误消息
   * @param {Number} duration 显示时长
   */
  showError(message, duration = 2000) {
    this.showToast('error', message, duration);
  },
  
  /**
   * 显示信息提示
   * @param {String} message 信息消息
   * @param {Number} duration 显示时长
   */
  showInfo(message, duration = 2000) {
    this.showToast('info', message, duration);
  },
  
  /**
   * 显示警告提示
   * @param {String} message 警告消息
   * @param {Number} duration 显示时长
   */
  showWarning(message, duration = 2000) {
    this.showToast('warning', message, duration);
  },
  
  /**
   * 捕获并处理异步操作错误
   * @param {Function} asyncFunc 异步函数
   * @param {Object} options 错误处理选项
   * @returns {Promise} 处理后的Promise
   */
  async catchAsync(asyncFunc, options = {}) {
    const defaultOpts = {
      moduleName: null,
      silent: false,
      throwError: false,
      showToast: true,
      loadingKey: null,
      errorType: ERROR_TYPES.UNKNOWN
    };
    
    const opts = { ...defaultOpts, ...options };
    
    try {
      return await asyncFunc();
    } catch (error) {
      // 根据错误类型处理
      switch (opts.errorType) {
        case ERROR_TYPES.API:
          this.handleApiError(error, opts.silent, {
            moduleName: opts.moduleName,
            throwError: opts.throwError,
            loadingKey: opts.loadingKey
          });
          break;
        case ERROR_TYPES.VALIDATION:
          this.handleFormError(error, null, {
            moduleName: opts.moduleName,
            throwError: opts.throwError,
            showToast: opts.showToast && !opts.silent
          });
          break;
        default:
          this.handlePageError(error, opts.moduleName, {
            showToast: opts.showToast && !opts.silent,
            throwError: opts.throwError,
            errorType: opts.errorType
          });
          break;
      }
      
      // 返回默认值或再次抛出
      if (opts.throwError) {
        throw error;
      }
      
      return null;
    }
  },
  
  /**
   * 在指定模块上下文中执行操作，自动处理错误
   * @param {Object} moduleStore Store模块对象
   * @param {Function} action 要执行的操作函数
   * @param {Object} options 错误处理选项
   * @returns {Promise} 处理结果
   */
  async withErrorHandling(moduleStore, action, options = {}) {
    // 保存当前Store
    const prevStore = this.store;
    
    // 绑定到指定的Store
    this.bindStore(moduleStore);
    
    try {
      return await this.catchAsync(
        () => action(moduleStore),
        {
          moduleName: moduleStore.moduleName || options.moduleName || null,
          ...options
        }
      );
    } finally {
      // 恢复原来的Store
      this.store = prevStore;
    }
  }
}; 